package com.nuanshui.heatedloan.fund.integration.pay.spring;

import com.nuanshui.framework.lang.ClassUtil;
import com.nuanshui.framework.springContext.SpringContextUtil;
import com.nuanshui.heatedloan.fund.integration.pay.annotation.PayHandlerComponent;
import com.nuanshui.heatedloan.fund.integration.pay.bean.PayConfirmHandlerMeta;
import com.nuanshui.heatedloan.fund.integration.pay.execute.PayConfirmHandler;
import com.nuanshui.heatedloan.fund.integration.pay.execute.PayExecute;
import com.nuanshui.heatedloan.fund.integration.pay.execute.PayExecuteFacade;
import com.nuanshui.heatedloan.fund.integration.pay.execute.PayExecuteFacadeImpl;
import com.nuanshui.heatedloan.fund.integration.pay.execute.sysexecute.AbstractPayExecute;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Set;


@Component
public class PayExecuteFactoryBean implements BeanFactoryAware, BeanPostProcessor, FactoryBean<PayExecuteFacade> {

	private BeanFactory beanFactory=null;
	
	private PayExecuteFacadeImpl payExecuteFacade = new PayExecuteFacadeImpl();

	private volatile boolean isInitEd = false;

	@Override
	public PayExecuteFacade getObject() throws Exception {
		
		return payExecuteFacade;
	}

	@Override
	public Class<?> getObjectType() {
		
		return PayExecuteFacade.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
	
       Class<?> targetClass = AopUtils.getTargetClass(bean);
	
		PayHandlerComponent payConfirmHandlerComponent =  AnnotationUtils.getAnnotation(targetClass, PayHandlerComponent.class);
		if(payConfirmHandlerComponent!=null && bean instanceof PayConfirmHandler)  {

			if (!isInitEd) {
				synchronized (payConfirmHandlerComponent) {
					if (!isInitEd) {
						isInitEd = true;
						Set<Class<?>> payConfirmHandlers = ClassUtil.getAnnotationClasses(PayHandlerComponent.class, "com.nuanshui.heatedloan.fund.integration.pay.execute.sysexecute");
						for (Class<?> payConfirmHandler : payConfirmHandlers) {
							PayHandlerComponent orderExecuteAnnotationTemp = payConfirmHandler.getAnnotation(PayHandlerComponent.class);
							if (orderExecuteAnnotationTemp != null) {
								PayConfirmHandlerMeta meta = new PayConfirmHandlerMeta();
								meta.setOrder(orderExecuteAnnotationTemp.order());
								meta.setPayConfirmHandler((PayConfirmHandler) SpringContextUtil.getBean(payConfirmHandler));
								meta.setNonsupportPayTypes(Arrays.asList(orderExecuteAnnotationTemp.nonsupportPayTypes()));
								meta.setSuportPayTypes(Arrays.asList(orderExecuteAnnotationTemp.suportPayTypes()));
								payExecuteFacade.getPayExecuteRegistrar().registerPayConfirmHandler(meta);
							}
						}
					}
				}
			}

			if(bean instanceof AbstractPayExecute ) {//表示为最后执行节点
				String code = payConfirmHandlerComponent.bizType().getCode();
				payExecuteFacade.getPayExecuteRegistrar().registerFinalPayConfirmHandler(code,(PayConfirmHandler)bean);
				payExecuteFacade.getPayExecuteRegistrar().register(code, (PayExecute)bean);
			}
		}
		
		return  bean;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory;		
	}

}
